#ifndef _E_SCENE_H_
#define _E_SCENE_H_

#include "EScreen.h"
#include "EPhScene.h"
#include "EGameObject.h"
#include "EVector.h"
#include "EStaticCollider.h"
#include "EEntityManager.h"
#include "EEventManager.h"
#include "EColor.h"
#include "EDesc.h"

#include "eH.h"
namespace engine
{
class ECharacter;
class ECharacterDesc;

//------------------------------------------------------------
class ESceneDesc : public EDesc
{
public:
  enum _eShadowAlgorithm
  {
    /// stencil shadows : sharp borders
    SHADOW_ALGO_VOLUMETRIC = 0,
    /// shadow map shadows : smooth but texture projection rendering
    SHADOW_ALGO_SHADOW_MAP,
    SHADOW_ALGO_COUNT
  };
  enum _eShadowBlendMode
  {
    /// faster, not accurate
    SHADOW_BLEND_MODE_MODULATIVE = 0,
    /// slower but accurate when rendering multiple lights
    SHADOW_BLEND_MODE_ADDITIVE,
    SHADOW_BLEND_MODE_COUNT
  };

  EPhSceneDesc        m_PhSceneDesc;
  _eShadowAlgorithm   m_eShadowAlgorithm;
  _eShadowBlendMode   m_eShadowBlendMode;
  EColor              m_cAmbientLight;

  ESceneDesc();
  bool    isValid() const;
};

//------------------------------------------------------------
class EScene : public ELoadable, public EEntityManager, public EEventManager
{
  friend class ESceneManager;

  void      updateShadowParams      ();
  ESceneDesc          m_Desc;
  EPhScene*           m_pPhScene;
  typedef map<const string, EScreen*>    EScreenMap;
  EScreenMap          m_mapScreens;
  EScreen*            m_pCurrentScreen;
  SceneManager&       m_OgreSceneManager;

protected:
  EScene( const ESceneDesc& desc, SceneManager& ogreSceneManager );
  ~EScene();

public:

  void              updateParams      ();
  virtual bool      update            ( const EGameTime& time );
  virtual bool      startGame         ( );
  virtual bool      updateGame        ( const EGameTime& time );
  virtual bool      endGame           ( );
  bool              startPhysicsSimulationComputing        (const EGameTime& gameTime);
  bool              endPhysicsSimulationComputing          ();
  bool              isPhysicsSimulationComputingEnded      () const;

  EScreen*          createScreen          ( const string& sName, const EScreenDesc& screenDesc );
  void              destroyScreen         ( const string& sName );
  ECharacter*       createCharacter       ( const string& sName, const ECharacterDesc& charDesc );
  EStaticCollider*  createStaticCollider  ( const EStaticColliderDesc& desc );
  /**
    * \return false if screen not found */
  bool              setCurrentScreen  ( const string& sName );

  virtual bool      load              ( );

  bool              initCharacterControllers();
  bool              releaseCharacterControllers();

  inline EPhScene*  getPhScenePtr() const { return m_pPhScene; }
};

} // end namespace

#endif